
#include "static_mac_cfg.h"



mac_table* total_mac_table[MAX_NODE_NUM];

void printf_mac_table()
{
	int i =0;
	int j = 0;
	
	for(i=0; i < MAX_NODE_NUM ; i++)
	{
		if(total_mac_table[i]== NULL)
		{
			continue;
		}

		printf("node_id=%d \n,",i);

		for(j = 0; j< total_mac_table[i]->total_size;j++)
		{
			printf("port=%llx,",total_mac_table[i]->table[j].port);
			printf("mac=%2x:%2x:%2x:%2x:%2x:%2x\n",total_mac_table[i]->table[j].mac[0],
												   total_mac_table[i]->table[j].mac[1],
												   total_mac_table[i]->table[j].mac[2],
												   total_mac_table[i]->table[j].mac[3],
													total_mac_table[i]->table[j].mac[4],
													total_mac_table[i]->table[j].mac[5]);
		}
	}
}

void mac_fwd_init(u8 *local_mac,u8 *pkt)
{
   u16 data_num = 0;
   
   u32 addr = 0;//配置的地址  
   u32 *data = NULL;

   //清空pkt
   bzero(pkt,2048);
   
   //data内容直接放到pkt中，省去再次赋值
   data = (u32 *)(pkt + sizeof(tsmp_header) + sizeof(tsmp_set_req_or_get_res_pkt_data));//配置的数据
	
	//mac转发表初始化，mac转发表总共8条表项，每条表项2个寄存器，总共16个寄存器地址

	addr = MAC_TABLE ;
	data_num = 2*MAX_MAC_ENTRY_NUM; 
	tsmp_set_req(local_mac,data_num,htonl(addr),pkt);//写请求

	bzero(pkt,2048);

	return ;
}


int cfg_broadcast_flag_reg(u8 *local_mac,u8 *pkt,u64 broadcast_flag)
{
   u16 data_num = 0;
   int ret = 0;
   
   u32 addr = 0;//配置的地址  
   u32 *data = NULL;

   //清空pkt
   bzero(pkt,2048);
   
   //data内容直接放到pkt中，省去再次赋值
   data = (u32 *)(pkt + sizeof(tsmp_header) + sizeof(tsmp_set_req_or_get_res_pkt_data));//配置的数据
	
	data[0] = htonl((broadcast_flag & 0x100000000) >> 32);
	data[1] = htonl(broadcast_flag & 0xffffffff);

	addr = BROADCAST_FLAG ;
	data_num = 2; 
	tsmp_set_req(local_mac,data_num,htonl(addr),pkt);//写请求

	 //配置验证
    ret = cfg_varify(local_mac,data_num,htonl(addr),pkt);

    //配置验证失败，程序退出
	if(ret == -1)
	{
		return -1;
	}

	return 0;

}


//解析转发表中的每个标签
int parse_mac_fwd_entry(cJSON *entry_json,u8 *data,u16 node_id,u8 entry_id)
{
	cJSON *tmp_json=NULL;

	//mac转发表表项格式： valid(1bit)+reserve1(14bit)+outport(33bit)+mac(48bit)+reserver2(32bit)
	u64  outport = 0;
	u64  tvalue = 0;
	u8  mac[6]={0};//MAC地址

	//printf("parse_mac_fwd_entry start! \n");

	if(data == NULL)
	{
		printf("parse_mac_fwd_entry,data = NULL! \n");
		return -1;
	}

	tmp_json =cJSON_GetObjectItem(entry_json, "mac");

	if(NULL == tmp_json)
	{
		printf("can not find  mac object!\n");
		return -1;
	}
	else
	{
		sscanf(tmp_json->valuestring,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",&mac[0],
													 &mac[1],
													 &mac[2],
													 &mac[3],
													 &mac[4],
													 &mac[5]);
		
		printf("mac %2x:%2x:%2x:%2x:%2x:%2x\n",mac[0],
											   mac[1],
											   mac[2],
											   mac[3],
												mac[4],
												mac[5]);
		memcpy(total_mac_table[node_id]->table[entry_id].mac,mac,6);
	}


	tmp_json =cJSON_GetObjectItem(entry_json, "outport");

	if(NULL == tmp_json)
	{
		printf("can not find  outport object!\n");
		return -1;
	}
	else
	{		
		sscanf(tmp_json->valuestring,"%llx",&tvalue);//十六进制转换
		outport = tvalue;

		total_mac_table[node_id]->table[entry_id].port = outport;
		total_mac_table[node_id]->table[entry_id].valid = 1;

		printf("outport： %llx \n",outport);			
	}
		
	data[0] = 0x80;
	data[1] = (outport & 0x0000000100000000) >> 32;
	data[2] = (outport & 0x00000000FF000000) >> 24;
	data[3] = (outport & 0x0000000000FF0000) >> 16;
	data[4] = (outport & 0x000000000000FF00) >> 8;
	data[5] = outport & 0x00000000000000FF;
	memcpy(&data[6],(u8 *)&mac[0],6);
	memset(&data[12], 0, 4);

	printf("parse_mac_fwd_entry end! \n");
	
	return 0;

}



 //循环解析转发表
 int static_mac_cfg_and_parse_mac_fwd(cJSON *entry_json,u8 *local_mac,u8 *pkt,u16 node_id)
{
	int array_num = 0;
	int i = 0;
	int ret = 0; 
	
	u16 data_num = 0;
	
	u32 addr = 0;//配置的地址	
	u8 *data = NULL;
	u8 cmp_mac[6] = {0};

	u8 cur_mac_fwd_num = 0;//当前转发表的数量
	cJSON *tmp_json=NULL;

	//验证是否已正确获取local_mac，如果是则可以继续运行
	if(memcmp(local_mac,cmp_mac,6) == 0)
	{
		printf("static_mac_cfg_and_parse_mac_fwd,error: local_mac is 0\n");
		return -1;
	}
	
	if(pkt == NULL)
	{
		printf("static_mac_cfg_and_parse_mac_fwd,pkt = NULL! \n");
		return -1;
	}

	//data内容直接放到pkt中，省去再次赋值
	data = (u8 *)(pkt + sizeof(tsmp_header) + sizeof(tsmp_set_req_or_get_res_pkt_data));//配置的数据
	
	//有多个节点情况
	if(entry_json->type == cJSON_Array)
	{
		array_num = cJSON_GetArraySize(entry_json);
		printf("array_num = %d \n", array_num);

		if(array_num == 0)
		{
			printf("static_mac_cfg_and_parse_mac_fwd, array_num = 0! \n");
			return -1;
		}

		for (i = 0; i < array_num; i++)
		{
			tmp_json = cJSON_GetArrayItem(entry_json,i);

			if (!tmp_json) 
			{
				printf("static_mac_cfg_and_parse_mac_fwd entry_json error, Error before: [%s]\n",cJSON_GetErrorPtr());
				return -1;
			}

			if(cur_mac_fwd_num == MAX_MAC_ENTRY_NUM)
			{
				printf("mac table cfg error! more than max mac entry num\n");
				return -1;
			}
			
			//每条表项包含两个data
			ret = parse_mac_fwd_entry(tmp_json,data,node_id,cur_mac_fwd_num);
			 //解析失败，程序退出
			if(ret == -1)
			{
				printf("parse_mac_fwd_entry error!\n");
				return -1;
			}

			addr = MAC_TABLE + 4*cur_mac_fwd_num;
		    data_num = 4; //mac转发表表项格式为valid(1bit)+pad(14bit)+outport(33bit)+mac(48bit)+reserve(32bit)，共128bit，硬件需要两个32bit存储
	
		    tsmp_set_req(local_mac,data_num,htonl(addr),pkt);//写请求

		    //配置验证
		    ret = cfg_varify(local_mac,data_num,htonl(addr),pkt);

		    //配置验证失败，程序退出
			if(ret == -1)
			{
				return -1;
			}

			cur_mac_fwd_num++;
		}
	}
	else if(entry_json->type == cJSON_Object)
	{
		if(cur_mac_fwd_num == MAX_MAC_ENTRY_NUM)
		{
			printf("mac table cfg error! more than max mac entry num\n");
			return -1;
		}
		
		//每条表项包含两个data
		ret = parse_mac_fwd_entry(entry_json,data,node_id,cur_mac_fwd_num);
	    //解析失败，程序退出
		if(ret == -1)
		{
			printf("parse_mac_fwd_entry error!\n");
			return -1;
		}

		addr = MAC_TABLE + 4*cur_mac_fwd_num;
	    data_num = 4; //mac转发表表项格式为valid(1bit)+pad(14bit)+outport(33bit)+mac(48bit)+reserve(32bit)，共128bit，硬件需要两个32bit存储

	    tsmp_set_req(local_mac,data_num,htonl(addr),pkt);//写请求

	    //配置验证
	    ret = cfg_varify(local_mac,data_num,htonl(addr),pkt);

	    //配置验证失败，程序退出
		if(ret == -1)
		{
			return -1;
		}

		cur_mac_fwd_num++;
	}	

	total_mac_table[node_id]->static_size = cur_mac_fwd_num;
	total_mac_table[node_id]->total_size = cur_mac_fwd_num;
	return 0;

}



int static_mac_cfg_and_parse_node_object(cJSON *node_json, u8 *pkt)
{
	u16 tvalue16 = 0;
	u16 hcp_mid = 0;
	u64  broadcast_flag = 0;
	int ret = 0;
		
	cJSON *hcp_mid_json=NULL;
	cJSON *mac_fwd_tbl_json=NULL;
	cJSON *broadcast_flag_json=NULL;
	cJSON *entry_json=NULL;
	
	u8 local_mac[6] = {0};

	// 获取节点hcp_mid信息
	hcp_mid_json =cJSON_GetObjectItem(node_json, "hcp_mid");

	if(NULL == hcp_mid_json)
	{
		printf("can not find  hcp_mid object!\n");
		return -1;
	}
	else
	{
		sscanf(hcp_mid_json->valuestring, "%hx", &tvalue16);
		hcp_mid = tvalue16;
		
		printf("hcp_mid 0x%hx \n", hcp_mid);

		get_hcp_mac_from_mid(local_mac,hcp_mid);

		if(hcp_mid >= MAX_NODE_NUM)
		{
			printf("hcp_mid error,hcp_mid >= MAX_NODE_NUM,hcp_mid  =%d",hcp_mid);
		}
		else
		{
			total_mac_table[hcp_mid] = (mac_table*)malloc(sizeof(mac_table));
			memset(total_mac_table[hcp_mid],0,sizeof(mac_table));

			total_mac_table[hcp_mid]->mid = hcp_mid;
		}
		
	}

	// 获取节点broadcast_flag信息
	broadcast_flag_json =cJSON_GetObjectItem(node_json, "broadcast_flag");

	if(NULL == broadcast_flag_json)
	{
		printf("can not find  broadcast_flag object!\n");
		return -1;
	}
	else
	{
		sscanf(broadcast_flag_json->valuestring,"%llx",&broadcast_flag);
		printf("broadcast_flag 0x%llx \n", broadcast_flag);

		ret = cfg_broadcast_flag_reg(local_mac,pkt,broadcast_flag);
		if(ret == -1)
		{
			return -1;
		}
	}

	// 获取节点mac_forward_table信息
	mac_fwd_tbl_json =cJSON_GetObjectItem(node_json, "mac_forward_table");

	if(NULL == mac_fwd_tbl_json)
	{
		printf("can not find  mac_forward_table object!\n");
		return -1;
	}
	else
	{
	 	//初始化mac转发表
		mac_fwd_init(local_mac,pkt);

		entry_json =cJSON_GetObjectItem(mac_fwd_tbl_json, "entry");
		if(NULL == entry_json)
		{
			printf("can not find  entry_json object!\n");
			return -1;
		}
		
        ret = static_mac_cfg_and_parse_mac_fwd(entry_json,local_mac,pkt,hcp_mid);
		if(ret == -1)
		{
			printf("static_mac_cfg_and_parse_mac_fwd error!\n");
			return -1;
		}		
	}
	
	printf("end static_mac_cfg_and_parse_node_object!\n");
	
	return 0;
}



int static_mac_cfg_and_parse_node(char* buf,u8 *pkt)
{
	int ret = 0;
	int array_num = 0;
	int i = 0;
	u16 tvalue16 = 0;
	
	cJSON *root_json=NULL;
	cJSON *static_mac_cfg_json=NULL;

	cJSON *node_json=NULL;
	cJSON *tmp_json=NULL;
	
	riprt_n(buf);
	root_json=cJSON_Parse(buf);

	if (!root_json) 
	{
		printf("parse root_json error, Error before: [%s]\n",cJSON_GetErrorPtr());
		return -1;
	}
	
	static_mac_cfg_json = cJSON_GetObjectItem(root_json, "static_mac_cfg");
	if (!static_mac_cfg_json) 
	{
		printf("parse static_mac_cfg error, Error before: [%s]\n",cJSON_GetErrorPtr());
		cJSON_Delete(root_json);
		return -1;
	}

	node_json = cJSON_GetObjectItem(static_mac_cfg_json, "node");
	if (!node_json) 
	{
		printf("parse node_json error, Error before: [%s]\n",cJSON_GetErrorPtr());
		cJSON_Delete(root_json);
		return -1;
	}

	//有多个节点情况
	if(node_json->type == cJSON_Array)
	{
		array_num = cJSON_GetArraySize(node_json);
		printf("array_num = %d \n", array_num);

		if(array_num == 0)
		{
			printf("parse_static_mac_info, node = NULL! \n");
			cJSON_Delete(root_json);
			return -1;
		}

		for (i = 0; i < array_num; i++)
		{
			tmp_json = cJSON_GetArrayItem(node_json,i);

			if (!tmp_json) 
			{
				printf("parse static_mac_node_entry_json error, Error before: [%s]\n",cJSON_GetErrorPtr());
				cJSON_Delete(root_json);
				return -1;
			}

			//获取单个节点的static_mac信息
			ret = static_mac_cfg_and_parse_node_object(tmp_json,pkt);
			if(ret == -1)
			{
				printf("static_mac_cfg_and_parse_node_object error!\n");
				cJSON_Delete(root_json);
				return -1;
			}
		}
	}
	else if(node_json->type == cJSON_Object)
	{
		//获取单个节点的static_mac信息
		ret = static_mac_cfg_and_parse_node_object(node_json,pkt);
	}

	cJSON_Delete(root_json);
	
    return ret;
	
}


int static_mac_cfg_and_parse_file(u8 *cfg_file_name,u8 *pkt)
{
	int ret = 0;
	
	FILE *fp;
	char *buf;
	fp = fopen(cfg_file_name,"r");

	if(fp == NULL)
	{
		printf("fopen %s error\n",cfg_file_name);
		return -1;
	}
			
    // 确定文件大小, 并将读取指针移回文件开始
    fseek(fp, 0, SEEK_END);
    long pos = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    if (pos <= 0) 
	{
        printf("%s Invalid!\n",cfg_file_name);
		fclose(fp);
		return -1;
    }
	
    // 根据文件大小申请内存空间, 注意这边要多申请1个字节用于存放'\0'
    buf = (char*)malloc(pos + 1);
    if (buf == NULL) {
        printf("No enough memory.");
		fclose(fp);
		return -1;
    }
	bzero(buf, pos + 1);
	
    // 读取文件内容至buff
    int nread = fread(buf, pos, 1, fp);
    if (!nread) {
        printf("Failed to read the config file.");
		free(buf);
		fclose(fp);
		return -1;
    }

    //解析json，获取各个节点静态MAC配置信息
	ret = static_mac_cfg_and_parse_node(buf,pkt);

	if(buf != NULL)
	{
		free(buf);
	}
	
    // 关闭文件
	fclose(fp);

	return ret;
}



//静态MAC配置的入口函数
int static_mac_cfg()
{
		
	int ret = 0;
	int i = 0;
	
	//申请空间，用于构造配置报文
	u8 *pkt = NULL;
	u8 *cfg_file_name = NULL;
	
	
	pkt = (u8 *)malloc(MAX_PKT_LEN);
	if(NULL == pkt)
	{
		printf("static_mac_cfg,malloc buf fail\n");
		return -1;
	}
	
	bzero(pkt,MAX_PKT_LEN);
	
	cfg_file_name = STATIC_MAC_JSON_FILE;//静态mac配置文本

	//初始化全网MAC转发表
	for(i=0; i<MAX_NODE_NUM; i++)
	{
		total_mac_table[i]=NULL;
	}

	//解析初始配置xml文本,解析一个表项，配置一个表项
	ret = static_mac_cfg_and_parse_file(cfg_file_name,pkt);
	if(ret == -1)
	{
		printf("parse_static_mac_cfg_xml fail\n");
		return -1;
	}

	//释放基础配置申请的空间
	free(pkt);

	printf_mac_table();
	
	printf("*************STATIC_MAC_CFG_FINISH********************\n");
	write_debug_msg("*************STATIC_MAC_CFG_FINISH********************\n");	

	return ret;
		
}


		
